<template>
  <div>
    <ElForm :model="formModel" v-bind="getBindValue" ref="formElRef">
      <ElRow v-bind="getRow">
        <slot name="formHeader"></slot>
        <template v-for="(schema, index) in getSchema" :key="schema.field + '-' + index">
          <FormItem
            :schema="schema"
            :formProps="getProps"
            :formModel="formModel"
            :setFormModel="setFormModel"
            :allDefaultValues="defaultValueRef"
            :formActionType="formActionType"
          >
            <template #[item]="data" v-for="item in Object.keys($slots)">
              <slot :name="item" v-bind="data || {}"></slot>
            </template>
          </FormItem>
        </template>
        <FormAction
          v-bind="getFormActionBindProps"
          @handleReset="resetFields"
          @handleSearch="handleSubmit"
        >
          <template #[item]="data" v-for="item in ['resetBefore', 'submitBefore', 'advanceBefore']">
            <slot :name="item" v-bind="data || {}"></slot>
          </template>
        </FormAction>
        <slot name="formFooter"></slot>
      </ElRow>
    </ElForm>
  </div>
</template>
<script lang="ts" setup>
import FormItem from './components/FormItem.vue';
import FormAction from './components/FormAction.vue';
import { computed, onMounted, reactive, type Ref, ref, unref, useAttrs } from 'vue';
import { useFormValues } from './hooks/useFormValues';
import type {
  AdvanceState,
  FormActionType,
  FormProps,
  FormSchema,
  Nullable,
  Recordable,
} from './types/form';
import { useFormEvents } from './hooks/useFormEvents';
import useAdvanced from './hooks/useAdvanced';
import type { EmitType } from './common/gloab';
import { basicFormProps } from './props';
import { ElRow, ElForm } from 'element-plus';
// eslint-disable-next-line no-undef
defineOptions({ name: 'BasicForm' });
const attrs = useAttrs();
const formElRef = ref<Nullable<FormActionType>>(null);
const schemaRef = ref<Nullable<FormSchema[]>>(null);
const emit = defineEmits(['advanced-change', 'reset', 'submit', 'register', 'field-value-change']);
const propsRef = ref<Partial<FormProps>>({});
const formModel = reactive<Recordable>({});
const defaultValueRef = ref<Recordable>({});
const props = defineProps(basicFormProps);

const advanceState = reactive<AdvanceState>({
  isAdvanced: false,
  hideAdvanceBtn: false,
  isLoad: false,
  actionSpan: 4,
});
const getBindValue = computed(() => ({ ...attrs, ...unref(propsRef) }) as Recordable);

const getProps = computed((): FormProps => {
  return { ...props, ...unref(propsRef) } as FormProps;
});
// console.log("getProps2222", getProps.value)

const getRow = computed((): Recordable => {
  const { rowProps } = unref(propsRef);
  return {
    ...rowProps,
  };
});
const getSchema = computed((): FormSchema[] => {
  const schemas: FormSchema[] = unref(schemaRef) || (unref(getProps).schemas as any);
  return schemas as FormSchema[];
});
const { initDefault, handleFormValues } = useFormValues({
  defaultValueRef,
  getSchema,
  formModel,
  getProps,
});

const {
  validate,
  validateField,
  resetFields,
  getFieldsValue,
  setFieldsValue,
  updateSchema,
  handleSubmit,
  appendSchemaByField,
  removeSchemaByField,
  clearValidate,
} = useFormEvents({
  emit: emit as EmitType,
  getProps,
  formModel,
  getSchema,
  defaultValueRef,
  formElRef: formElRef as Ref<FormActionType>,
  schemaRef: schemaRef as Ref<FormSchema[]>,
  handleFormValues,
});
useAdvanced({
  advanceState,
  emit: emit as EmitType,
  getProps,
  getSchema,
  formModel,
  defaultValueRef,
});
const formActionType: Partial<FormActionType> = {
  setProps,
  validate,
  validateField,
  resetFields,
  getFieldsValue,
  setFieldsValue,
  updateSchema,
  removeSchemaByField,
  appendSchemaByField,
  clearValidate,
};

onMounted(() => {
  emit('register', formActionType);
  initDefault();
});

function setFormModel(key: string, value: any, schema: FormSchema, isValid?: boolean) {
  // console.log('value......', value);

  formModel[key] = value;
  if (isValid) {
    validateField(key).catch((_) => {});
  }
  emit('field-value-change', { key, value, schema });
}

async function setProps(formProps: Partial<FormProps>) {
  // console.log("获取到的初始数据", formProps)
  propsRef.value = { ...unref(propsRef), ...formProps };
  // console.log('获取到的初始数据', propsRef.value);
}
const getFormActionBindProps = computed((): Recordable => ({ ...getProps.value, ...advanceState }));

defineExpose({ formElRef });
</script>
